//
//  LoginViewController.swift
//  QingLiuSwift
//
//  Created by xyanl on 2023/8/11.
//

import UIKit
import WebKit
import Photos
import Kingfisher
import JKSwiftExtension
import Localize_Swift

// Swift之WKWebView的介绍和使用 https://www.jianshu.com/p/0be0b6546f8c
// https://www.jianshu.com/p/403853b63537?utm_medium=seo-recommended-notes&utm_source=mobile

// 【Swift】WKWebView与JS的交互使用
// https://zhuanlan.zhihu.com/p/264815414

fileprivate let titleKeyPath = "title"
fileprivate let estimatedProgressKeyPath = "estimatedProgress"

class BaseWebViewController: BaseViewController {
    
    private var url: String = ""
    private var isNavBarHide = false
    /// 指定是否将web视图标题显示为导航栏标题。
    /// 默认值为“false”，它将导航栏标题设置为URL请求的URL主机名。
    private var displaysWebViewTitle: Bool = false
    
    private var html: String = ""
    
    private var isBackRoot: Bool = false
    
    var isDidFinish: Bool = false
    
    /// 提示框内容,如果有内容,会展示个 toast
    var message: String = ""
    
    // WKWebView
    lazy var wkWebView: WKWebView = {
        // 创建WKWebView
        var webView = WKWebView(frame: CGRectMake(0, 0, xScreenW, xScreenH), configuration: configuration)
        // 让webview翻动有回弹效果
        webView.scrollView.bounces = true
        // 只允许webview上下滚动
        webView.scrollView.alwaysBounceVertical = true
        // 实现 WKNavigationDelegate 协议
        webView.navigationDelegate = self
        // 实现 WKUIDelegate 协议
        webView.uiDelegate = self
        
        // uniapp ios 页面底部空白一块
        // https://blog.51cto.com/u_16175449/13161104
        
        //        webView.evaluateJavaScript("document.documentElement.style.webkitTouchCallout='none';document.documentElement.style.webkitUserSelect='none';", completionHandler: nil)
        
        return webView
    }()
    
    lazy var configuration: WKWebViewConfiguration = {
        // 创建WKWebViewConfiguration
        let configuration = WKWebViewConfiguration()
        
        // WKUserContentController 是 WebKit 框架的一部分，通常与 WKWebView 一起使用。
        // 其主要功能允许开发者将JavaScript中的信息发送到原生代码中，从而实现更多复杂的交互。
        // 主要功能
        // 消息处理：允许JavaScript通过消息发送机制与本地应用进行通信。
        // 脚本注入：可以在加载页面时注入JavaScript代码，从而影响页面行为。
        let userContentController = WKUserContentController()
        // 配置WKWebViewConfiguration的WKUserContentController
        configuration.userContentController = userContentController
        
        // 给WKWebView与Swift交互起一个名字：callbackHandler，WKWebView给Swift发消息的时候会用到
        // 此句要求实现WKScriptMessageHandler协议
        configuration.userContentController.add(self, name: "callbackHandler")
        // 添加 H5 交互
        configuration.userContentController.add(self, name: "NativeBridge")
        
        return configuration
    }()
    
    // 进度条
    lazy var progressView: UIProgressView = {
        var progressView = UIProgressView(frame: CGRectMake(0, 0, xScreenW, 4.0))
        progressView.progressTintColor = UIColor.red
        progressView.trackTintColor = UIColor.clear
        return progressView
    }()
    
    init(html: String, displaysWebViewTitle: Bool = true, isNavBarHide: Bool = false) {
        self.html = html
        self.displaysWebViewTitle = displaysWebViewTitle
        self.isNavBarHide = isNavBarHide
        super.init(nibName: nil, bundle: nil)
    }
    
    init(url: String, displaysWebViewTitle: Bool = true, isNavBarHide: Bool = false, isBackRoot: Bool = false) {
        self.url = url
        self.displaysWebViewTitle = displaysWebViewTitle
        self.isNavBarHide = isNavBarHide
        self.isBackRoot = isBackRoot
        super.init(nibName: nil, bundle: nil)
    }
    
    init() {
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        initNav()
        initUI()
        wkWebViewObserver()
        WechatManager.shared.delegate = self
        
        if let uRL = URL(string: url) {
            xLog("加载 web url：\(url)")
            wkWebView.load(URLRequest(url: uRL))
        } else {
            xLog("url 失效 \(url.count)")
        }
        
        if !html.isEmpty {
            wkWebView.loadHTMLString(html, baseURL: nil)
        }
        
        if !message.isEmpty {
            YLHUD.showMessage(message)
        }
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        onNativeShow(className)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        onNativeHide(className)
    }
    
    @objc override func backAction() {
        
        if isBackRoot {
            navigationController?.popToRootViewController(animated: true)
            return
        }
        
        if wkWebView.canGoBack {
            wkWebView.goBack()
        } else {
            super.backAction()
        }
    }
    
    deinit {
        xLog("deinit -- BaseWebViewController")
        // deallocAll()
        // wkWebView.configuration.userContentController.removeAllScriptMessageHandlers()
    }
    
    func deallocAll() {
        xLog("deallocAll -- BaseWebViewController")
        wkWebView.uiDelegate = nil
        wkWebView.scrollView.delegate = nil
        wkWebView.navigationDelegate = nil
        
        wkWebView.removeObserver(self, forKeyPath: titleKeyPath, context: nil)
        wkWebView.removeObserver(self, forKeyPath: estimatedProgressKeyPath, context: nil)
    }
    
    // 刷新当前页面
    func reloadWebPage() {
        if let url = wkWebView.url {
            let request = URLRequest(url: url)
            wkWebView.load(request)
            xLog("刷新页面")
            
        } else {
            // 处理 URL 不存在的情况
        }
    }
    
    func onNativeShow(_ name: String) {
        if !isDidFinish {
            return
        }
        let jsCode = "window.onNativeShow()"
        wkWebView.evaluateJavaScript(jsCode) { result, error in
            if error == nil {
                xLog("[\(name)] 调用 H5 方法成功： \(jsCode) [\(String(describing: result))])")
            } else {
                xLog("[\(name)] 调用 H5 方法失败： \(jsCode) [\(String(describing: result))]")
            }
        }
    }
    
    func onNativeHide(_ name: String) {
        let jsCode = "window.onNativeHide()"
        wkWebView.evaluateJavaScript(jsCode) { result, error in
            if error == nil {
                xLog("[\(name)] 调用 H5 方法成功： \(jsCode) [\(String(describing: result))])")
            } else {
                xLog("[\(name)] 调用 H5 方法失败： \(jsCode) [\(String(describing: result))]")
            }
        }
    }
    
}

private extension BaseWebViewController {
    func initNav() {
        navigationItem.leftBarButtonItem = UIBarButtonItem(
            image: UIImage(named: "ic_back_333333")?.withRenderingMode(.alwaysOriginal),
            style: .done,
            target: self,
            action: #selector(backAction)
        )
        
        vhl_navBarHide = isNavBarHide
        
    }
    
    func initUI() {
        view.addSubview(wkWebView)
        view.addSubview(progressView)
        progressView.isHidden = true
        wkWebView.sizeToFit()
    }
    
    /// 添加 webView 监听
    func wkWebViewObserver() {
        // 监听 title
        wkWebView.addObserver(self, forKeyPath: titleKeyPath, options: .new, context: nil)
        // 进度条的进度监听
        wkWebView.addObserver(self, forKeyPath: estimatedProgressKeyPath, options: .new, context: nil)
    }
    
    func loadURL(URLString: String) {
        if let uRL = URL(string: URLString) {
            self.url = URLString
            xLog("加载 web url：\(url)")
            wkWebView.load(URLRequest(url: uRL))
        } else {
            xLog("url 失效 \(url.count)")
        }
    }
    
    // 退出登录
    func logout() {
        // IM 退出登录
        ZIMKit.disconnectUser()
        // 清空即构缓存的数据
        ZegoUIKit.shared.uninit()
        cleanCacheAndCookie()
        // 清空本地存储的数据
        UserProfile.clear()
        DispatchQueue.main.async {
            UIApplication.shared.applicationIconBadgeNumber = 0
            BaseTabBarController.updateTabBarBadgeValue(index: 2, count: 0)
        }
    }
}

extension BaseWebViewController {
    // 清理缓存
    func cleanCacheAndCookie() {
        xLog("清 webView 缓存")
        let dateSince1970 = Date(timeIntervalSince1970: 0) // 获取1970年以来的所有数据
        WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: dateSince1970) {
            // 清除完成后的回调
            // 如果你还需要清除与WKWebView相关的cookies，可以使用以下方法：
            HTTPCookieStorage.shared.removeCookies(since: Date(timeIntervalSince1970: 0))
            xLog("清除完成后的回调")
        }
        
    }
}

/// 两个协议分别是：WKNavigationDelegate WKScriptMessageHandler
/// WKNavigationDelegate：判断页面加载完成，只有在页面加载完成了，才能在swift中调webview中的js方法
/// WKScriptMessageHandler: 在webview中给swift发消息时要用到协议中的一个方法来接收
extension BaseWebViewController: WKUIDelegate, WKNavigationDelegate {
    
    // 加载完毕以后执行，自适应屏幕宽度，有的屏幕不自适应，需要自适应屏幕宽度
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        xLog("H5 加载完成")
        isDidFinish = true
        webView.evaluateJavaScript("console.log('Hello, World!')") { (result, error) in
            if let error = error {
                print("Error executing script: \(error)")
            } else {
                print("Script executed successfully")
            }
        }
    }
    
    // 处理网页加载失败
    private func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
        self.progressView.progress = 0
    }
    
    // 页面开始加载时调用
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        // xLog("开始加载...")
    }
    
    // 当内容开始返回时调用
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!){
        // xLog("当内容开始返回...")
    }
    
    // 页面加载失败
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        xLog(error)
        self.progressView.progress = 0
    }
}

var lastActionTime: NSDate?

extension BaseWebViewController: WKScriptMessageHandler {
    // userContentController(_:didReceive:) 方法是用来处理接收到的消息的实现。在这个方法内，我们通过 message.name 检查消息的类型，然后再根据 message.body 处理消息内容。
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        
        if let lat = lastActionTime {
            let diff = lat.timeIntervalSinceNow
            if diff > -1.0 {
                return
            }
        }
        lastActionTime = NSDate()
        xLog("message.name: \(message.name)")
        
        
        if message.name != "NativeBridge" {
            return
        }
        let bodyString = message.body as! String
        xLog("JS传递的参数: \(bodyString)")
        guard let bodyDic = bodyString.toDictionary() else {
            return
        }
        var url = ""
        // 打开连接
        let webViewStr = bodyDic["webview"] as! String
        if webViewStr == "zWebView" {
            // 跳转货代
            url = SystemEnvManager.shared.forwarderUrl
        }
        if webViewStr == "zWebViewOline" {
            // 线上展会
            url = SystemEnvManager.shared.exhibitionUrl
        }
        if webViewStr == "zWebViewShop" {
            // 商城
            url = SystemEnvManager.shared.shopUrl
        }
        
        if webViewStr == "zWebViewDaixiao" {
            // 代销商品
            url = SystemEnvManager.shared.consignmentUrl
        }
        
        // 执行事件
        let action = bodyDic["action"] as! String
        //        if action == "navigateBack" {
        //            // 返回
        //            backAction()
        //        }
        
        switch action {
        case "navigateBack":
            backAction()
            
        case "navigateTo":
            // 路由前进 打开新界面 重新加载链接
            navigateToVC(bodyDic, url)
            
        case "redirectTo":
            // 关闭当前路由跳转到下个路由 重新加载当前界面
            redirectToVC(bodyDic, url)
            
        case "upDateUser":
            // 更新用户头像
            updateUserInfo(bodyDic)
            
        case "login":
            // 被动退出登录
            logout()
            YLAlert(controller: self, title: "登录过期，请重新登录".localized(.login), actionTitles: ["重新登录".localized(.login)], cancelTitle: nil) { action, index in
                // 显示登录页面
                xKeyWindow.rootViewController = BaseNavigationController(rootViewController: LoginMainController())
            }
            
        case "activeLogin":
            // 退出登录
            logout()
            // 显示登录页面
            xKeyWindow.rootViewController = BaseNavigationController(rootViewController: LoginMainController())
            
        case "makePhoneCall":
            // 拨打电话
            if let mobile = bodyDic["data"] as? String {
                JKGlobalTools.callPhone(phoneNumber: mobile) { isSuccess in }
            }
            
        case "initiateChat":
            // IM 聊天
            let data = bodyDic["data"]
            var conversationID: String = ""
            if data is String {
                conversationID = data as! String
            }
            
            if data is Int {
                conversationID = String(data as! Int)
            }
            
            
                // 判断积分是否为零, 为零的时候弹积分充值
            MineMainViewModel.loadUserInfo(String(UserProfile.userId)) { userModel in
                if UserProfile.country == 0 {
                    // 中国人
                    if (userModel?.score ?? 0) <= 0 {
                        self.scoreNotEnough()
                    } else {
                        self.push(ZIMKitMessagesListVC(conversationID: conversationID, type: .peer, conversationName: ""))
                    }
                } else {
                    // 其他国家的 小于 0 的栏
                    if (userModel?.score ?? 0) < 0 {
                        self.scoreNotEnough()
                    } else {
                        self.push(ZIMKitMessagesListVC(conversationID: conversationID, type: .peer, conversationName: ""))
                    }
                }
                
            }
            
        case "call":
            // 视频聊天
            let data = bodyDic["data"] as! [String: Any]
            let userId = data["userId"] as! Int
            // 1：需要翻译， 2：不需要翻译
            let type = data["type"] as! Int
            checkVideoCallScore(userId: String(userId), isTranslation: type == 1)
            
        case "wxPay":
            payWX(bodyDic)
            
        case "aliPay":
            payAli(bodyDic)
            
        case "downloadFile":
            downloadFile(bodyDic)
            
        case "openLive":
            openLive(bodyDic)
            
        case "joinLive":
            watchLive(bodyDic)
            
        case "sendGood":
            shareGoodsToIM(bodyDic)
            
        case "getCurrentPosition":
            // 获取车辆位置
            location()
            
        case "setLockOrientation":
            break
            
        default: break
        }
        
    }
    
    // MARK: - Web Action
    fileprivate func navigateToVC(_ bodyDic: [String: Any], _ URL: String) {
        // 路由前进 打开新界面 重新加载链接
        var url = URL
        
        let urlPath = bodyDic["data"] as! String
        if urlPath.hasSuffix("?") {
            // 不包含参数
            url = url + urlPath + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
            
        } else if urlPath.contains("?") {
            // 包含参数
            url = url + urlPath + "&" + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
            
        } else {
            url = url + urlPath + "?" + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
        }
        
        if url.isEmpty {
            xLog("url 没有数据")
            return
        }
        push(BaseWebViewController(url: url, isNavBarHide: true))
    }
    
    fileprivate func redirectToVC(_ bodyDic: [String: Any], _ URL: String) {
        var url = URL
        let urlPath = bodyDic["data"] as! String
        if urlPath.hasSuffix("?") {
            // 不包含参数
            url = url + urlPath + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
            
        } else if urlPath.contains("?") {
            // 包含参数
            url = url + urlPath + "&" + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
            
        } else {
            url = url + urlPath + "?" + H5UrlManager.urlParameter(xIphoneStatusBarHeight, xIphoneBottomSafeHeight)
        }
        
        if url.isEmpty {
            xLog("url 没有数据")
            return
        }
        xLog("url \(url)")
        push(BaseWebViewController(url: url, isNavBarHide: true, isBackRoot: true))
    }
    
    
    
    fileprivate func updateUserInfo(_ bodyDic: [String: Any]) {
        // 更新头像
        xLog(bodyDic)
        let data = bodyDic["data"] as! [String: String]
        if let userModel = JsonUtil.modelFromDictionary(data, UserModel.self) {
            userModel.id = UserProfile.userId
            userModel.saveUser()
            
            UserProfile.avatar = userModel.avatar
            UserProfile.username = userModel.username
            UserProfile.usernameRu = userModel.usernameRu
            
            ZIMKitCore.shared.localUser?.avatarUrl = userModel.avatar
            ZIMKitCore.shared.localUser?.name = userModel.username
            ZIMKitCore.shared.updateUserAvatarUrl(userModel.avatar)
        }
    }
    
    fileprivate func payWX(_ bodyDic: [String: Any]) {
        // 微信支付
        if !WechatManager.isInstalled() {
            YLHUD.showMessage("请先安装微信 APP，再来支付。")
            return
        }
        
        let data = bodyDic["data"] as! String
        if let sdkParams = data.toDictionary() {
            xLog("sdkParams \(sdkParams as NSDictionary)")
            let payReq = JsonUtil.modelFromDictionary(sdkParams, WechatPayReq.self)!
            WechatManager.shared.pay(payReq: payReq)
        }
    }
    
    fileprivate func payAli(_ bodyDic: [String: Any]) {
        let data = bodyDic["data"] as! String
        xLog("支付宝 order : [\(data)]")
        var orderString: String = data
        // 去掉首尾的双引号，后台返回的数据多一套双引号
        if orderString.hasPrefix("\"") {
            orderString = String(orderString.dropFirst())
        }
        if orderString.hasSuffix("\"") {
            orderString = String(orderString.dropLast())
        }
        
        // 应用注册scheme,在AliSDKDemo-Info.plist定义URL types
        // NOTE: 调用支付结果开始支付 跳转支付宝支付时只有当 processOrderWithPaymentResult 接口的 completionBlock 为 nil 时会使用这个 bolock
        // 只有当 AlipaySDK.defaultService().processOrder(withPaymentResult: url, standbyCallback: nil) 的 standbyCallback 为空
        // iOS 端无法 H5 支付
        // iOS 不安装支付宝客户端的时候不能打开 H5 的页面：在调用支付的时候取下 [[[UIApplication shareApplication] windows] index:0] 看看 hidden 属性是否为 YES，如果是说明隐藏了 window，H5 就出不来了，设置为 NO 即可 [[[UIApplication sharedApplication] windows] objectAtIndex:0]; 或把 App 中第 0 个 window 的 hidden 属性改成 NO 即可。
        // https://opendocs.alipay.com/support/01rftl
        
        AlipaySDK.defaultService().payOrder(orderString, fromScheme: "alipaygluz") { result in
            DispatchQueue.main.async {
                let resultDic = result as! [String: Any]
                xLog("[支付宝] 支付跳转支付宝钱包进行支付，处理支付结果 = \(resultDic as NSDictionary)")
                let resultStatus = "\(resultDic["resultStatus"] ?? "")"
                
                if resultStatus == "9000" {
                    xLog("[支付宝] 支付成功")
                    YLHUD.showMessage("支付成功".localized(.store)) {
                        self.reloadWebPage()
                    }
                    
                } else if resultStatus == "4000" {
                    YLHUD.showMessage("未安装应用程序".localized(.store))
                } else if resultStatus == "6001" {
                    YLHUD.showMessage("取消支付".localized(.store))
                } else {
                    let errMsg = resultDic["memo"] as! String
                    YLHUD.showMessage("支付失败".localized(.store) + errMsg)
                }
            }
        }
    }
    
    fileprivate func downloadFile(_ bodyDic: [String: Any]) {
        // 下载文件
        let data = bodyDic["data"] as! [String: Any]
        xLog("下载文件 \(data as NSDictionary)")
        guard let url = data["url"] as? String, let type = data["type"] as? Int else { return }
        if type == 1 {
            downloadFile(url: url)
        } else if type == 2 {
            saveImageToPhotoLibrary(from: url)
            //            saveImageToPhotoLibrary(from: url) { saved, _ in
            //                if saved {
            //                    YLHUD.showMessage("保存成功")
            //                } else {
            //                    YLHUD.showMessage("保存失败")
            //                }
            //            }
        }
        // let url = "https://gluz-oss.oss-cn-beijing.aliyuncs.com/uploads/20231102/1dc5edd90320372bedf234ac1e88fb5c.jpg"
        
        
    }
    
    private func saveImageToPhotoLibrary(from urlString: String) {
        guard let URL = URL(string: urlString) else { return }
        KingfisherManager.shared.downloader.downloadImage(with: URL) { value in
            switch value {
            case .success(let result):
                
                PHPhotoLibrary.requestAuthorization { status in
                    switch status {
                    case .authorized, .limited:
                        // 5. 保存图片到相册
                        PHPhotoLibrary.shared().performChanges({
                            PHAssetChangeRequest.creationRequestForAsset(from: result.image)
                        }) { success, error in
                            DispatchQueue.main.async { YLHUD.showMessage("保存成功") }
                        }
                    default:
                        // let error = NSError(domain: "Permission denied", code: 2)
                        DispatchQueue.main.async { YLHUD.showMessage("保存失败") }
                    }
                }
                
            case .failure:
                DispatchQueue.main.async { YLHUD.showMessage("下载失败") }
            }
        }
    }
    
    //    private func saveImageToPhotoLibrary(from urlString: String, completion: ((Bool, Error?) -> Void)? = nil) {
    //        // 1. 检查URL有效性
    //        guard let url = URL(string: urlString) else {
    //            let error = NSError(domain: "Invalid URL", code: 0)
    //            completion?(false, error)
    //            return
    //        }
    //
    //        // 2. 下载图片数据
    //        URLSession.shared.dataTask(with: url) { data, _, error in
    //            if let error = error {
    //                DispatchQueue.main.async { completion?(false, error) }
    //                return
    //            }
    //
    //            // 3. 转换为UIImage
    //            guard let data = data, let image = UIImage(data: data) else {
    //                let error = NSError(domain: "Image data is corrupted", code: 1)
    //                DispatchQueue.main.async { completion?(false, error) }
    //                return
    //            }
    //
    //            // 4. 检查并请求相册权限
    //            PHPhotoLibrary.requestAuthorization { status in
    //                switch status {
    //                case .authorized, .limited:
    //                    // 5. 保存图片到相册
    //                    PHPhotoLibrary.shared().performChanges({
    //                        PHAssetChangeRequest.creationRequestForAsset(from: image)
    //                    }) { success, error in
    //                        DispatchQueue.main.async { completion?(success, error) }
    //                    }
    //                default:
    //                    let error = NSError(domain: "Permission denied", code: 2)
    //                    DispatchQueue.main.async { completion?(false, error) }
    //                }
    //            }
    //        }.resume()
    //    }
    
    
    fileprivate func openLive(_ bodyDic: [String: Any]) {
        // 展会直播
        if let data = bodyDic["data"] as? [String: Any], let eId = data["id"] as? Int {
            GLLive_Helper.openLiveStreamRoom(exhibitionId: eId)
        }
    }
    
    /// 观看直播
    fileprivate func watchLive(_ bodyDic: [String: Any]) {
        //{"action":"joinLive","data":{"userId":1523,"id":2},"webview":"zWebViewOline"}
        if  let data = bodyDic["data"] as? [String: Any],
            let eId = data["id"] as? Int,
            let userId = data["userId"] as? Int {
            
            // 主播自己不让进自己的直播间
            if userId == UserProfile.userId {
                YLAlert(controller: currentViewController() ?? xKeyWindow.rootViewController!, title: "不能给自己申请1v1会议".localized(.live), actionTitles: ["确定".localized(.login)], cancelTitle: nil)
                
            } else {
                //                if let role = UserProfile.role {
                //                    switch role {
                //                    case .interpreter:
                //                        // 翻译不让进
                //                        YLHUD.showMessage("直播间已满".localized(.live))
                //                    default:
                // 进入直播间
                let target = LiveAPI.checkIsLiving(userId: "\(userId)")
                YLHUD.showLottie()
                YLRequest.request(target) { result in
                    switch result {
                    case .success(let res):
                        YLHUD.hideHUD()
                        if let roomId: String = res.dataDictionary["roomId"] as? String, !roomId.isEmpty { // 直播中
                            // let country = res.dataDictionary["country"]
                            GLLive_Helper.joinLiveSteamingRoom(exhibitionId: eId, hostId: "\(userId)", roomId: roomId)
                            
                        } else {
                            // 未开直播
                            GLLive_Helper.appointment1V1(receiveUserId: userId)
                        }
                        
                    case .failure(_):
                        YLHUD.hideHUD()
                        //                            }
                        //                        }
                    }
                }
            }
        }
    }
    
    /// 分享商品到 IM sendGood
    fileprivate func shareGoodsToIM(_ bodyDic: [String: Any]) {
        // 下载文件
        guard let data = bodyDic["data"] as? [String: Any] else {
            return
        }
        // xLog(data as NSDictionary)
        if let model = JsonUtil.modelFromDictionary(data, ShareGoodsToIMModel.self) {
            ZIMKit.sendCustomMessage(data.toJSONString()!, to: String(model.userId), type: .peer, subType: 1)
            let vc = ZIMKitMessagesListVC(conversationID: String(model.userId), type: .peer, conversationName: "")
            vc.imScore()
            push(vc)
        }
    }
    
}

extension BaseWebViewController {
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        guard let theKeyPath = keyPath , object as? WKWebView == wkWebView else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }
        
        if displaysWebViewTitle && theKeyPath == titleKeyPath {
            title = wkWebView.title
        }
        
        if keyPath == estimatedProgressKeyPath {
            
            self.progressView.alpha = 1.0
            self.progressView.setProgress(Float(wkWebView.estimatedProgress), animated: true)
            
            //进度条的值最大为1.0
            if(wkWebView.estimatedProgress >= 1.0) {
                
                UIView.animate(withDuration: 0.3, delay: 0.1, options: .curveEaseInOut, animations: { () -> Void in
                    self.progressView.alpha = 0.0
                }, completion: { (finished:Bool) -> Void in
                    self.progressView.progress = 0
                })
            }
        }
    }
}

// MARK: - WechatManagerDelegate
extension BaseWebViewController: WechatManagerDelegate {
    func wechatPayResp(code: WechatResultCode, errMsg: String) {
        xLog("微信支付 code \(code.rawValue), errMsg: \(errMsg)")
        if code == .success {
            /// 更新订单状态为 2，支付成功
            YLHUD.showMessage("支付成功".localized(.store)) {
                self.reloadWebPage()
            }
            
        } else if code == .cancel {
            YLHUD.showMessage("取消支付".localized(.store))
            
        } else {
            YLHUD.showMessage("支付失败".localized(.store))
        }
    }
}

// MARK: - 下载文件
extension BaseWebViewController: UIDocumentPickerDelegate {
    
    func downloadFile(url: String) {
        
        guard let taskUrl = URL(string: url) else { return }
        debugPrint("文件下载url:\(taskUrl)")
        let request = URLRequest(url: taskUrl)
        let session = URLSession(configuration: .default)
        session.downloadTask(with: request) { [weak self] tempUrl, response, error in
            guard let self = self, let tempUrl = tempUrl, error == nil else {
                debugPrint("文件下载失败")
                return
            }
            debugPrint("文件下载完成\(tempUrl)")
            // 下载完成之后会自动删除temp中的文件，把文件移动到document中。
            let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            debugPrint("文件下载完成 documentsDirectory \(documentsDirectory)")
            // 建议使用的文件名，一般跟服务器端的文件名一致
            let destinationPath = documentsDirectory.appendingPathComponent(response?.suggestedFilename ?? "")
            // 如果存在同名的
            if FileManager.default.fileExists(atPath: destinationPath.path) {
                do {
                    try FileManager.default.removeItem(atPath: destinationPath.path)
                } catch _ {
                    
                }
            }
            debugPrint("文件下载 document下的可保存的url:\(destinationPath)")
            do {
                // 文件移动至document
                try FileManager.default.copyItem(atPath: tempUrl.path, toPath: destinationPath.path)
                // main
                DispatchQueue.main.async {
                    self.saveFileToPhone(url: destinationPath)
                }
            } catch let error {
                debugPrint(error)
                xLog(error.localizedDescription)
            }
        }.resume()
    }
    
    func saveFileToPhone(url: URL) {
        let picker = UIDocumentPickerViewController(url: url, in: .exportToService)
        picker.delegate = self
        picker.modalPresentationStyle = .formSheet
        self.present(picker, animated: true)
    }
    
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        // 保存成功
        xLog("文件 保存成功")
        YLHUD.showMessage("保存成功，可去文件APP中查看")
    }
    
    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        xLog("文件 取消保存")
    }
}

// MARK: - 定位
extension BaseWebViewController: LocationManagerDelegate {
    func authorizationStatus(_ status: Bool) {
        if !status {
            xLog("未授权")
        }
    }
    
    func currentLocation(_ location: CLLocation) {
        LocationManager.shared.stopLocation()
        xLog("Swift 调用 Html 方法")
        let json = [
            "longitude": location.coordinate.longitude,
            "latitude": location.coordinate.latitude
        ].toJSONString()!
        
        let inputJS = "setCurrentPosition (" + json + ")"
        wkWebView.evaluateJavaScript(inputJS) { (response, error) in
            xLog(inputJS + " \(response.debugDescription) ")
        }
    }
    
    func location() {
        let manager = LocationManager.shared
        manager.checkAuthorizationStatus(delegate: self)
        manager.startLocation()
    }
    
}
